package model 
{
	import controller.EventBus;
	import controller.GameViewControllerEvent;
	import controller.NPCModelEvent;
	import controller.RootViewControllerEvent;
	import controller.ZeldaComponentEvent;
	import controller.ZeldaModelEvent;
	import model.data.InventoryObjectTypes;
	import model.data.MovementDirections;
	/**
	 * ...
	 * @author Gaz Williams
	 * 
	 * the model for the players character 
	 * zelda moves 'on rails'
	 * and has an inventory of items 
	 * zelda moves one square at a time on the grid held in game model
	 * 
	 */
	public class ZeldaModel 
	{
		private var worldWidthInTiles:uint;
		private var worldHeightInTiles:uint;
		
		private var column:int = 0;
		private var row:int = 0;
		
		private var bus:EventBus;
		
		private var previousDirection:MovementDirections;
		private var _currentDirection:MovementDirections;
		public function get currentDirection():MovementDirections 
		{
			return _currentDirection;
		}
		public function set currentDirection(value:MovementDirections):void 
		{
			previousDirection = _currentDirection;
			_currentDirection = value;
		}
		
		public var currentlyHeld:InventoryObjectTypes;
		
		public function ZeldaModel(worldWidthInTiles:uint, worldHeightInTiles:uint, spawnColumn:int, spawnRow:int) 
		{
			this.worldWidthInTiles 	= worldWidthInTiles;
			this.worldHeightInTiles = worldHeightInTiles;
			
			column 	= spawnColumn;
			row 	= spawnRow;
			
			currentlyHeld 		= new InventoryObjectTypes(InventoryObjectTypes.NOTHING);
			currentDirection 	= new MovementDirections(MovementDirections.IDLE);
			
			//listen for guideMapEvents
			bus = EventBus.getInstance();
			
			bus.addEventListener(ZeldaComponentEvent.MOVE_COMPLETED, handleZeldaComponentMoved);
			bus.addEventListener(GameViewControllerEvent.PLAYER_HIT_GUIDE_MARKER, handleGuideMarker);
			bus.addEventListener(GameViewControllerEvent.PLAYER_INTERACTED_WITH_NPC, handleNPCInteraction);
			bus.addEventListener(GameViewControllerEvent.PLAYER_INTERACTION_COMPLETED, handlePlayerInteractionCompleted);
			bus.addEventListener(NPCModelEvent.RIGHT_ITEM, handleRightItemGiven);
			
			update();
		}
		
		public function dispose():void 
		{
			bus.removeEventListener(ZeldaComponentEvent.MOVE_COMPLETED, handleZeldaComponentMoved);
			bus.removeEventListener(GameViewControllerEvent.PLAYER_HIT_GUIDE_MARKER, handleGuideMarker);
			bus.removeEventListener(NPCModelEvent.RIGHT_ITEM, handleRightItemGiven);
			bus.removeEventListener(GameViewControllerEvent.PLAYER_INTERACTED_WITH_NPC, handleNPCInteraction);
			bus.removeEventListener(GameViewControllerEvent.PLAYER_INTERACTION_COMPLETED, handlePlayerInteractionCompleted);
		}
		
		private function handleRightItemGiven(e:NPCModelEvent):void 
		{
			currentlyHeld = e.forInventoryItem;
			
			var data:InventoryObjectTypes = currentlyHeld;
			bus.dispatchEvent(new ZeldaModelEvent(ZeldaModelEvent.INVENTORY_UPDATED, data));
		}
		
		
		private function handleGuideMarker(e:GameViewControllerEvent):void 
		{
			currentDirection = e.data as MovementDirections;
		}
		
		private function handleZeldaComponentMoved(e:ZeldaComponentEvent):void 
		{
			//current direction remains unchanged.
			update();
		}
		
		public function update():void 
		{
			//move one tile in that direction
			switch (currentDirection.type) 
			{
				case MovementDirections.UP:
					//trace("up");
					row--;
				break;
				case MovementDirections.DOWN:
					//trace("down");
					row++;
				break;
				case MovementDirections.LEFT:
					//trace("left");
					column--;
				break;
				case MovementDirections.RIGHT:
					//trace("right");
					column++;
				break;
				default:
				case MovementDirections.IDLE:
					//trace("fail");
					//do nothing
				break;
			}
			
			//bound to screen
			if (column < 0)					column = 0;
			if (column > worldWidthInTiles) column = worldWidthInTiles;
			if (row < 0) 					row = 0;
			if (row > worldHeightInTiles) 	row = worldHeightInTiles;
			
			//let everyone know where we are now.
			var data:Object = { column:this.column, row:this.row, facing:currentDirection };
			bus.dispatchEvent(new ZeldaModelEvent(ZeldaModelEvent.POSITION_UPDATED, data));
		}
		
		private function handleNPCInteraction(e:GameViewControllerEvent):void 
		{
			currentDirection = new MovementDirections(MovementDirections.IDLE);
		}
		
		//resume direction
		private function handlePlayerInteractionCompleted(e:GameViewControllerEvent):void 
		{
			currentDirection = previousDirection;
			update(); //move one square beyond collision zone
		}
		
	}

}